/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bff.slimserver.musicjukebox.lib;

import java.awt.Image;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bff.slimserver.musicobjects.SlimPlayableItem;

/**
 *
 * @author bill
 */
public class ArtManager {

    private static HashMap<SlimPlayableItem, AlbumClass> albumMap = new HashMap<SlimPlayableItem, AlbumClass>();
    private static List<AlbumClass> albumList = new ArrayList<AlbumClass>();
    private static final Runtime runtime = Runtime.getRuntime();
    private static boolean checking;
    private static final int REMOVE_COUNT = 50;

    /**
     * @return the albumMap
     */
    private static HashMap<SlimPlayableItem, AlbumClass> getAlbumMap() {
        return albumMap;
    }

    public static synchronized Image getArt(SlimPlayableItem item) {
        AlbumClass ac = getAlbumMap().get(item);

        if (ac == null) {
            ac = new AlbumClass(item);
            getAlbumMap().put(item, ac);
            getAlbumList().add(ac);
        } else {
            ac.setDate(Calendar.getInstance().getTime());
        }

        if (!checking) {
            checking = true;
            new Thread(new Runnable() {

                @Override
                public void run() {
                    checkMemory();
                    checking = false;
                }
            }).start();
        }
        return ac.getImage();
    }

    private static void checkMemory() {
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();

        while (true) {
            try {
                Thread.sleep(15000);
            } catch (InterruptedException ex) {
                Logger.getLogger(ArtManager.class.getName()).log(Level.SEVERE, null, ex);
            }
            maxMemory = runtime.maxMemory();
            allocatedMemory = runtime.totalMemory();
            freeMemory = runtime.freeMemory();

            double percentage = allocatedMemory / (double) maxMemory;
            if (percentage > .75) {

                List<AlbumClass> removeList = new ArrayList<AlbumClass>();
                Collections.sort(getAlbumList());

                int count = 0;
                for (AlbumClass ac : getAlbumList()) {
                    removeList.add(ac);
                    if (++count > REMOVE_COUNT) {
                        break;
                    }
                }

                for (AlbumClass ac : removeList) {
                    getAlbumList().remove(ac);
                    getAlbumMap().remove(ac.getItem());
                    ac = null;
                }

            }
        }
    }

    /**
     * @return the albumList
     */
    private static List<AlbumClass> getAlbumList() {
        return albumList;
    }

    private static class AlbumClass implements Comparable<AlbumClass> {

        private SlimPlayableItem item;
        private Date date;
        private Image image;

        public AlbumClass(SlimPlayableItem item) {
            this.item = item;
            this.date = Calendar.getInstance().getTime();
            this.image = item.getImage();
        }

        /**
         * @return the item
         */
        public SlimPlayableItem getItem() {
            return item;
        }

        /**
         * @param item the item to set
         */
        public void setItem(SlimPlayableItem item) {
            this.item = item;
        }

        /**
         * @return the date
         */
        public Date getDate() {
            return date;
        }

        /**
         * @param date the date to set
         */
        public void setDate(Date date) {
            this.date = date;
        }

        /**
         * @return the image
         */
        public Image getImage() {
            return image;
        }

        /**
         * @param image the image to set
         */
        public void setImage(Image image) {
            this.image = image;
        }

        @Override
        public int compareTo(AlbumClass o) {
            return getDate().compareTo(o.getDate());
        }
    }
}
